'use strict'

import { app } from 'electron'
import initWindow from './services/windowManager'
import DisableButton from './config/DisableButton'
import electronDevtoolsInstaller, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
const ipcMain = require('electron').ipcMain;
const { SerialPort } = require("serialport");
import axios from 'axios'
const { exec } = require("child_process")
const WebSocket = require('ws');

var serialport = ''
var b //支付金额
var paymentCode
var cashierSetupData
var printData
var workerProcess
var cashBuffer
var paymentType
var printerTypes //打印类型
var parallelports //并口类型
var diviceNos //激活码
var amountMoney = 0 //营业额
var wss
var webws

function onAppReady() {
  initWindow()
  DisableButton.Disablef12()
  if (process.env.NODE_ENV === 'development') {
    electronDevtoolsInstaller(VUEJS_DEVTOOLS)
      .then((name) => console.log(`installed: ${name}`))
      .catch(err => console.log('Unable to install `vue-devtools`: \n', err))
  }
}

//打开本地开发环境监测版本更新
Object.defineProperty(app, 'isPackaged', {
  get() {
    return true;
  }
});
//禁止程序多开，此处需要单例锁的同学打开注释即可
// const gotTheLock = app.requestSingleInstanceLock()
// if(!gotTheLock){
//   app.quit()
// }
app.isReady() ? onAppReady() : app.on('ready', onAppReady)
// 解决9.x跨域异常问题
app.commandLine.appendSwitch('disable-features', 'OutOfBlinkCors')

app.on('window-all-closed', () => {
  // 所有平台均为所有窗口关闭就退出软件
  app.quit()
})
app.on('browser-window-created', () => {
  console.log('window-created')
})

if (process.defaultApp) {
  if (process.argv.length >= 2) {
    app.removeAsDefaultProtocolClient('electron-vue-template')
    console.log('有于框架特殊性开发环境下无法使用')
  }
} else {
  app.setAsDefaultProtocolClient('electron-vue-template')
}
// 用户登录开机时是否自动启动
ipcMain.on('handle-checkbox', (event, isChecked) => {
  app.setLoginItemSettings({
    openAtLogin: isChecked,
    // 如果应用以管理员身份运行，设置此选项为true可避免UAC（用户账户控制）对话框在Windows上弹出。
    openAsHidden: false, // macOS特有的，当设置为true时，应用会隐藏式启动
  })
})

//监听打开串口
ipcMain.on('ck', async (event, val, baud, type, printerType, parallelport, diviceNo) => {
  wss = new WebSocket.Server({ port: 8085 });
  wss.on('connection', function connection(ws) {
    webws = ws
  });
  diviceNos = JSON.parse(diviceNo)
  printerTypes = printerType
  parallelports = parallelport
  serialport = new SerialPort({
    path: val,
    baudRate: baud,
    dataBits: 8,
    parity: "none",
    stopBits: 1,
    autoOpen: false,
  });
  serialport.open((err) => {
    if (!err) {
      event.returnValue = '串口true'
    } else {
      event.returnValue = '串口已经打开'
    }
  });
  serialport.removeAllListeners();  //清除所有监听器
  let bool = true;
  let buffer = null;
  serialport.on("data", data => { //监听串口消息
    if (bool) {
      // 第一次
      buffer = data;
      bool = false;
      let handle = setInterval(() => {
        bool = true;
        clearInterval(handle);
        data = buffer;
        if (!data) {
          workerProcess = exec('msg /time 2 * "串口消息获取失败~"')
        }
        if (type == 1) { //窗口读取
        } else if (type == 2) { //客显模式
          data = data.toString()
          console.log('Data:', data.toString())    // data为监听到的内容，即下位机返回的数据
          let aaaa = data.split('A')
          b = aaaa[1] //支付金额
        } else if (type == 3) { //虚拟串口
          const buffer = Buffer.from(data);
          if (buffer.length > 5) { //不知道为啥发两次消息，长的是可用的消息
            let uarray = Array.prototype.slice.call(data)
            let hex_array = uarray.map(el => {
              let str = Number(el).toString(16)
              if (str.length == 1) {
                return "0" + str;
              }
              return str;
            })
            let content = hex_array.toString().replace(/,/g, "")
            cashBuffer = data //串口拿到的原始数据
            if (!paymentCode && paymentCode == undefined) { //现金结账
              let _res = curl('14', cashierSetupData, content)
              console.log(_res);
            } else {
              curl(paymentCode, cashierSetupData, content)
            }
          }
          event.returnValue = 123456456456456
        } else if (type == 4) { //金额搜索
        }
      }, 500);
    } else {
      // 追加
      buffer = Buffer.concat([buffer, data]);
      return;
    }
  })
})

//监听到付款码的操作
ipcMain.on('ck1', async (event, code, cashierSetup) => {
  let codeJson = JSON.parse(code);
  paymentCode = codeJson.code //付款码或者退款码
  paymentType = codeJson.type //支付类型
  cashierSetupData = cashierSetup
  if (cashierSetup.getAmountType == 2) { //客显
    if (codeJson.code && b) {
      let _res = await curl(codeJson.code, cashierSetup, '')
      event.returnValue = _res
    } else {
      if (!b) {
        event.returnValue = ''
        workerProcess = exec('msg /time 5 * "金额获取失败~"')
        return
      }
    }
    event.returnValue = ''
  } else if (cashierSetup.getAmountType == 3) { //小票
    let cashierSetupStr = ''
    if (cashierSetup.keysData != undefined && cashierSetup.keysData != '') {
      cashierSetupStr = JSON.parse(cashierSetup.keysData)
      if (paymentType == 'refund') { //退款需要发送的热键
        cashierSetupStr = [
          { key: '', value: { codetext: 'F1', code: 112 } },
          { key: '', value: { codetext: 'Enter', code: 13 } },
        ]
      }
      print(cashierSetupStr)
      // if (codeJson.type == 'pay') {
      //   workerProcess = exec('msg /time 2 * "支付中~"')
      // }
    } else {
      workerProcess = exec('msg /time 5 * "虚拟串口模式必须设置按键~"')
    }
    event.returnValue = ''
  }
})

ipcMain.on('ck2', (event) => {
  event.returnValue = printData
})

//支付
async function curl(code, cashierSetup, content = '') {
  let payType
  let regex = /^\d{0,2}/;
  let result
  let type
  let cashierSetupStr = ''
  let price = ''
  if (code != '14') { //非现金结账
    result = code.match(regex)[0];
    if (result == 13) {
      payType = "微信";
    } else if (result == 28) {
      payType = "支付宝";
    } else if (result == '01') {
      payType = "数字人民币";
    }
    if (paymentType == 'pay') {
      type = 'pay_data'
    } else {
      type = 'refund_data'
    }
    if (cashierSetup != null && cashierSetup.keysData != undefined) { //支付成功执行
      cashierSetupStr = JSON.parse(cashierSetup.keysData)
    }

    if (cashierSetup != null && cashierSetup.getAmountType == 2) { //客显
      price = cheng(Number(b), 100)
    }
  } else {
    result = '现金'
    type = 'data_report'
  }
  const jsonData = {
    "type": type,
    "data": {
      "link_id": "1217752501201",
      "network": 1,
      "device_id": "EC16EAAE3C40",
      "auth_code": code, //付款码
      "auth_channel": 1,
      "content": content,
      "price": price
    },
    "res": 0,
    "err": "ok"
  }
  if (type == 'refund_data') { //小票模式退款
    jsonData.data.refund_code = paymentCode
  }
  try {
    if (code != '14') {
      let msg = ''
      if (paymentType == 'pay') {
        msg = '用户支付中~'
      } else {
        msg = '退款中~'
      }
      workerProcess = exec(`msg /time 3 * ${msg}`)
    }
    const res = await axios.post(`https://divapi.hbryjf.com/api/unified/payOrder/${diviceNos}`, jsonData)
    if (res.data.code == 9999) {
      workerProcess = exec(`msg /time 5 * 支付失败~`)
      return
    }
    if (res.data.data.res != 0) {
      workerProcess = exec(`msg /time 5 * ${res.data.data.err}`)
      return
    }
    if (res.data.code == 0) {
      const _data = res.data.data.data
      //统计营业额
      if (_data.amount && res.data.data.type == 'pay_result') {
        amountMoney += _data.amount
        webws.send(amountMoney / 100)
      } else if (_data.amount && res.data.data.type == 'refund_result') {
        if (amountMoney != 0) {
          amountMoney -= _data.amount
          webws.send(amountMoney / 100)
        }
      }
      //打印小票
      if (code != '14') { //非现金
        if (printerTypes == 4) { //并口打印
          if (cashierSetup.getAmountType == 3) { //小票模式
            if (paymentType == 'pay') {
              runExec('', _data.qrhex, cashierSetup.getAmountType); //调用打印方法
            } else { //退款
              runExec('', '', cashierSetup.getAmountType); //调用打印方法
            }
          }
          if (cashierSetup.getAmountType == 2) { //客显模式
            // 任何你期望执行的cmd命令，ls都可以
            let cmdStr = `\t${payType}-付款回执\n\n商户名称:${_data.mchName}\n设备信息:12345678945647\n交易时间:${_data.successTime}\n订单号:${_data.orderNo}\n付款方式:${payType}\n流水号:${_data.platformMchOrderNo}\n------------------------------\n订单总额:${_data.amount / 100}\n用户实付:${_data.amount / 100}\n------------------------------\n`
            runExec(cmdStr, _data.qrhex, cashierSetup.getAmountType); //调用打印方法
            if (cashierSetupStr) {
              setTimeout(() => {
                print(cashierSetupStr)
              }, 300)
            }
          }
        } else if (printerTypes == 2 && cashierSetup.getAmountType == 2) { //客显驱动打印
          _data.money = b
          _data.payType = payType
          setTimeout(() => { //先打印付款回执，在发送热键
            if (cashierSetupStr) {
              print(cashierSetupStr)
            }
          }, 300);
          return _data
        }
        else if (printerTypes == 2 && cashierSetup.getAmountType == 3) {// 小票模式驱动打印
          if (paymentType == 'pay') {
            runExec('', _data.qrhex, cashierSetup.getAmountType, content); //调用打印方法
          } else { //退款
            runExec('', '', cashierSetup.getAmountType, content); //调用打印方法
          }
          // _data.money = _data.amount / 100
          // _data.payType = payType
          // printData = _data
          // printData = cashBuffer
        }
        paymentCode = undefined //不是现金结账要把付款码清空，用于区分结账模式是线上或者线下
      } else { //现金结账打印
        if (printerTypes == 2) { //驱动
          runExec('', '', 3, content); //调用打印方法
        } else {
          runExec('', '', 3); //调用打印方法
        }
      }
    } else {
      console.log('接口调用失败');
    }
  } catch (e) {
    if (e.code  == 'ECONNREFUSED') {
      workerProcess = exec(`msg /time 5 * "服务器连接失败!"`)
      return
    }
  }

}

//执行cmd命令
function runExec(str, qrCode, getAmountType, content = '') {
  let fs = require("fs");
  //json数组
  if (str && getAmountType == 2) { //客显模式需要自己拼小票
    const iconv = require('iconv-lite');
    let strBuffer = iconv.encode(str, 'gb2312');
    fs.writeFile("data.txt", strBuffer, function (err) {
      if (err) {
        console.log(err);
      } else {
        console.log("file success！！！")
      }
    })
  }
  if (getAmountType == 3) { //小票模式直接打印
    let bufferObject
    if (content != '') {
      fs.writeFile("cashBuffer.txt", content, function (err) {
        if (err) {
          console.log(err);
        } else {
          console.log("file success！！！")
        }
      })
    } else {
      bufferObject = Buffer.from(cashBuffer, 'hex')
      fs.writeFile("cashBuffer.txt", bufferObject, function (err) {
        if (err) {
          console.log(err);
        } else {
          console.log("file success！！！")
        }
      })
    }
  }
  if (qrCode != '') { //退款不打印二维码
    let bufferObject = ''
    if (getAmountType == 3 && printerTypes == 2) { //小票驱动打印二维码不需要转换
      bufferObject = qrCode
    } else {
      bufferObject = Buffer.from(qrCode, 'hex')
    }
    fs.writeFile("qrCode.txt", bufferObject, function (err) {
      if (err) {
        console.log(err);
      } else {
        console.log("file success！！！")
      }
    })
  }
  // 子进程名称
  // 执行命令行，如果命令不需要路径，或就是项目根目录，则不需要cwd参数
  if (printerTypes == 4) { //并口模式
    if (parallelports == 1) {
      if (getAmountType == 2) {
        workerProcess = exec('type data.txt > lpt1')
      }
      if (getAmountType == 3) {
        workerProcess = exec('type cashBuffer.txt > lpt1')
      }
      if (qrCode != '') {
        setTimeout(() => {
          workerProcess = exec('type qrCode.txt > lpt1')
        }, 500)
      }
    } else if (parallelports == 2) {
      if (getAmountType == 2) {
        workerProcess = exec('type data.txt > lpt2')
      }
      if (getAmountType == 3) {
        workerProcess = exec('type cashBuffer.txt > lpt2')
      }
      if (qrCode != '') {
        setTimeout(() => {
          workerProcess = exec('type qrCode.txt > lpt2')
        }, 500)
      }
    } else if (parallelports == 3) {
      if (getAmountType == 2) {
        workerProcess = exec('type data.txt > lpt3')
      }
      if (getAmountType == 3) {
        workerProcess = exec('type cashBuffer.txt > lpt3')
      }
      if (qrCode != '') {
        setTimeout(() => {
          workerProcess = exec('type qrCode.txt > lpt3')
        }, 500)
      }
    }
  } else if (getAmountType == 3 && printerTypes == 2) {
    workerProcess = exec('USBprint.exe XP-58 cashBuffer.txt')
    if (qrCode != '') {
      setTimeout(() => {
        workerProcess = exec('USBprint.exe XP-58 qrCode.txt')
      }, 500)
    }
  }

  // 不受child_process默认的缓冲区大小的使用方法，没参数也要写上{}：workerProcess = exec(cmdStr, {})

  // 打印正常的后台可执行程序输出
  workerProcess.stdout.on('data', function (data) {
    console.log('stdout: ' + data);
  });

  // 打印错误的后台可执行程序输出
  workerProcess.stderr.on('data', function (data) {
    console.log('stderr: ' + data);
  });

  // 退出之后的输出
  workerProcess.on('close', function (code) {
    console.log('out code：' + code);
  })
}

//发送热键
const print = (cashierSetupStr) => {
  cashierSetupStr.forEach((item, index) => {
    setTimeout(() => {
      let a = 'sendKey.exe ' + item.value.code
      workerProcess = exec(a)
    }, 200 * index)
  })
}

const cheng = (arg1, arg2) => {
  if (arg1 && arg2) {
    var m = 0, s1 = arg1.toString(), s2 = arg2.toString();
    try { m += s1.split(".")[1].length } catch (e) { }
    try { m += s2.split(".")[1].length } catch (e) { }
    let val = Number(s1.replace(".", "")) * Number(s2.replace(".", "")) / Math.pow(10, m);
    return String(val).replace('-', '')
  }
}

// 写入日志
const writeLog = (data) => {
  let fs = require("fs");
  fs.writeFile("operationLog.json", data, { flag: 'a' }, function (err) {
    if (err) {
      console.log(err);
    } else {
      console.log("file success！！！")
    }
  })
}

//客显模式退款同步营业额
ipcMain.on('refund', (event, price) => {
  if (amountMoney != 0) {
    amountMoney -= price
    webws.send(amountMoney / 100)
  }
  event.returnValue = ''
})



